use std::path::PathBuf;
use structopt::StructOpt;
use std::io::{Result, Seek, SeekFrom, Error, ErrorKind};
use crate::task::Task;
use std::fs::{OpenOptions, File};

#[derive(Debug, StructOpt)]
pub enum Action {
    /// 将task添加到journal_file
    Add {
        /// task描述
        #[structopt()]
        task: String
    },
    /// 通过position位置删除一个task
    Done {
        #[structopt()]
        position: usize
    },
    /// task列表
    List,
}

#[derive(Debug, StructOpt)]
#[structopt(
name = "Rusty Journal",
about = "A command line to-do app written in Rust"
)]
pub struct CommandLineArgs {
    #[structopt(subcommand)]
    pub action: Action,
    /// Use a different journal file.
    #[structopt(parse(from_os_str), short, long)]
    pub journal_file: Option<PathBuf>,
}

pub fn add_task(journal_path: PathBuf, task: Task) -> Result<()> {
    let mut file: File = OpenOptions::new().read(true).write(true).create(true).open(journal_path)?;

    let mut tasks: Vec<Task> = collect_task(&mut file)?;

    println!("tasks is {:?}", tasks);

    tasks.push(task);

    serde_json::to_writer(file, &tasks)?;
    //
    // println!("json is {:?}", task);
    Ok(())
}

#[test]
fn test_add_task() {
    let path = PathBuf::from("./test.json");
    let task = Task::new("测试task".to_string());
    println!("path is {:?}", path);
    let result = add_task(path, task);
    eprintln!("{:?}", result)
}

#[test]
fn test_complete_task() {
    let path = PathBuf::from("./test.json");
    let result = complete_task(path, 0);
    eprintln!("{:?}", result)
}

fn collect_task(mut file: &File) -> Result<Vec<Task>> {
    file.seek(SeekFrom::Start(0))?;
    let tasks:Vec<Task> = match serde_json::from_reader(file) {
        Ok(tasks) => tasks,
        Err(e) if e.is_eof() => Vec::new(),
        Err(e) => Err(e)?
    };
    file.seek(SeekFrom::Start(0))?;
    return Ok(tasks);
}

pub fn complete_task(journal_path: PathBuf, position: usize) -> Result<()> {
    let mut file = OpenOptions::new().write(true).read(true).create(true).open(journal_path)?;
    let mut tasks: Vec<Task> = collect_task(&mut file)?;

    if tasks.len() <= position {
        return Err(Error::new(ErrorKind::InvalidInput, "不存在的任务"));
    }
    tasks.remove(position);
    file.set_len(0)?;
    serde_json::to_writer(file, &tasks)?;
    Ok(())

}

pub fn list_task(journal_path: PathBuf) -> Result<()> {
    let file = OpenOptions::new().read(true).open(journal_path)?;
    let tasks = collect_task(&file)?;
    if tasks.is_empty() {
        println!("不存在任务");
    }
    for (i, it) in tasks.iter().enumerate() {
        println!("task {} is {}", i, it);
    };
    Ok(())
}

#[test]
fn test_list_task() {
    let result = list_task(PathBuf::from("./test.json"));
    assert_eq!((), result.unwrap());
}